/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.yongw.MouseMove;

import static cn.yongw.MouseMove.ReceiveDataUtil.receiveData;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import javafx.application.Platform;
import javafx.scene.control.TextArea;
import javafx.scene.text.Text;

/**
 *
 * @author 张永伟
 */
public class WifiJavaServer2 extends JavaServer{   
    Socket socket;
    DataOutputStream out;
    DataInputStream in;
    private TextArea ta;
    private Text tvMsg;
    private String hostName;
    Format format;    
    ArrayList<String> allServerHost = new ArrayList<>();
    Thread searchThread;
    boolean isRunning =true;
    
    /**
     * @param ta 展示通知的窗口
     * @param tvMsg 展示主机ip的窗口
     */   
    public WifiJavaServer2(TextArea ta, Text tvMsg) throws HostNullException {
        this.ta = ta;
        this.tvMsg = tvMsg;
        format = new SimpleDateFormat("YYYY年yy月dd日HH:mm:ss.SSS");        
        Enumeration<NetworkInterface>networkInterfaces;
        try {
            networkInterfaces = NetworkInterface.getNetworkInterfaces();
             NetworkInterface networkInterface;
            Enumeration<InetAddress> inetAddress;
            InetAddress inetAddres;
            while(hostName== null && networkInterfaces.hasMoreElements()){
                networkInterface = networkInterfaces.nextElement();
                inetAddress = networkInterface.getInetAddresses();
                while(hostName== null && inetAddress.hasMoreElements()){
                    inetAddres = inetAddress.nextElement();
                    if(inetAddress != null && inetAddres instanceof Inet4Address){
                        if(networkInterface.getName().contains("wl") || networkInterface.getName().contains("WL") ||
                                networkInterface.getDisplayName().contains("Microsoft Hosted Network"))
                            hostName = inetAddres.getHostAddress();
                    }                    
                }
            }
            if(hostName == null)
                throw new HostNullException("电脑未连接至无线网络");   
        } catch (SocketException ex) {
            ex.printStackTrace();
        }        
        isRunning =true;
    }    
    @Override
    public void run(){
        try{
            if(hostName != null){
                tvMsg.setText("本机IP为:" + hostName);                    
             //   ServerSocket serverSocket = new ServerSocket(8000);
                String preStr = hostName.substring(0, hostName.lastIndexOf(".") + 1); //获得前缀
                searchThread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while(isRunning){
                            ArrayList<Thread>threads= new ArrayList<>();
                            for(int i = 1; i < 255; i++) //创建256个线程池
                                if(!(preStr + i).equals(hostName)) {
                                    threads.add(new Thread(new FindServerClass(preStr + i)));
                                    threads.get(threads.size() - 1).start();
                                }
                            for(Thread thread:threads){ //等待所有线程都执行完毕
                                try {
                                    thread.join();
                                } catch (InterruptedException e) {
                                    System.out.println("监控查找ip线程被打断");
                                }
                            }
                            threads.clear();
                            
                            try {
                                Thread.sleep(3000);
                            } catch (InterruptedException ex) {
                                ex.printStackTrace();
                            }
                        }
                    }
                });
                searchThread.start();
                Platform.runLater(() -> ta.appendText(format.format(new Date()) +  " -> 正在查找客户端\n"));                
                while(isRunning){
                    try{
                       // System.out.println("server start scanning………");
                  //      Platform.runLater(() -> ta.appendText(format.format(new Date()) + "-> 无线鼠标wifi电脑端已启动,等待手机端连接\n"));                    
                        while(allServerHost.size() == 0){ // 还没找到手机
                            Thread.sleep(1000);
                        }
                        socket = new Socket(allServerHost.get(0), 8000);
                        out = new DataOutputStream(socket.getOutputStream());
                        in = new DataInputStream(socket.getInputStream());
                        out.write("connect".getBytes()); //连接
                        byte[] buffer = new byte[1024];
                        in.read(buffer);
                        String command = new String(buffer).trim();//一定要加trim，要不然不一样
                        if(command.contains("sure")){
                            System.out.println("receive connect");
                            Platform.runLater(() -> ta.appendText(format.format(new Date()) +
                                    "-> 连接成功,客户端IP为:"+socket.getInetAddress().getHostAddress()+",可以开始操作\n"));                    
                            System.out.println("start readdata……");
                            receiveData(in, ta);             
                            System.out.println("end receive, wait for another connect");                               
                            allServerHost.clear();//已经连接了就清空
                            Platform.runLater(() -> ta.appendText(format.format(new Date()) + "-> 连接断开,等待重新连接\n"));                        
                        }
                        in.close();
                        socket.close();
                    }catch(IOException ex) {
                        Platform.runLater(() -> ta.appendText(format.format(new Date()) +
                                    "-> 客户端主动断开连接\n"));
                        allServerHost.clear();//已经连接了就清空
                        ex.printStackTrace();
                    }
                }
            }
        } catch (InterruptedException ex) {
           ex.printStackTrace();
        }
    }
    /**
     * 根据给定的ip，判断该ip是否可用
     */
    private class FindServerClass implements Runnable{
        private String ip;
        private FindServerClass(String ip){
            this.ip = ip;
        }
        @Override
        public void run() {
            synchronized (this){
                if(checkIP(ip) && checkIPPort(ip, 8000) && !allServerHost.contains(ip)){
                    allServerHost.add(ip);
                    Platform.runLater(() -> ta.appendText(format.format(new Date()) +  " -> 检索到客户端+"+ip+"接入网络，等待客户端\n\t搜索连接！\n") );
                }
            }
        }
    }
    static boolean checkIPPort(String ip, int port){
        Socket socket = new Socket();
        try{
            socket.connect(new InetSocketAddress(ip, port), 8000);
            socket.getOutputStream().write("search".getBytes()); //发出查找信号
            return true;
        } catch (IOException ex) {
            return false;
        }finally{
            if(socket !=null){
                try{
                    socket.close();
                } catch (IOException ex) {
                    System.out.println(ex.getLocalizedMessage());
                }
            }
        }
    }
    static boolean checkIP(String ip){
        try{
            return InetAddress.getByName(ip).isReachable(500);
        } catch (IOException ex) {
            System.out.println(ex.getLocalizedMessage());
            return false;
        }
    }
   
    /**
     * 关闭服务器
     */
    @Override
    public void closeServer(){
        isRunning=false;
        try {
            searchThread=null;
            allServerHost.clear();
            if(in!=null)
                in.close();
            if(out!=null)
                out.close();
            if(socket!=null)
                socket.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

